﻿using System;
using OfficeOpenXml;
using System.Text;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace SourceCode
{
    /// <summary>
    /// Excel 转化器
    /// </summary>
    internal class Translators
    {
        string ExcelDir;
        string JsonDir = "/Json";
        string CodeDir = "/Code";

        private bool Init()
        {
            FolderSelectDialog dialog = new FolderSelectDialog();
            dialog.Title = "请选择Excel所在文件夹";
            if (dialog.ShowDialog())
            {
                if (!string.IsNullOrEmpty(dialog.FileName) && dialog.FileName.Length > 5)
                {
                    ExcelDir = dialog.FileName;
                    DirectoryInfo info = new DirectoryInfo(dialog.FileName);
                    string absolutePath = info.Parent.FullName;
                    JsonDir = absolutePath + JsonDir;
                    CodeDir = absolutePath + CodeDir;
                    Directory.CreateDirectory(JsonDir);
                    Directory.CreateDirectory(CodeDir);
                    return true;
                }
            }
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("路径错误，未识别的目录！");
            Console.ResetColor();
            return false;
        }
        /// <summary>
        /// 生成代码
        /// </summary>
        private void GenerateCode()
        {
            string[] excelFiles = Directory.GetFiles(ExcelDir, "*.xlsx");
            foreach (string excelFile in excelFiles)
            {
                StringBuilder stringBuilder = new StringBuilder();
                string fileName = Path.GetFileNameWithoutExtension(excelFile);
                using (var package = new ExcelPackage(excelFile))
                {
                    stringBuilder.AppendLine($"namespace ExcelConfig");
                    stringBuilder.AppendLine("{");
                    var worksheets = package.Workbook.Worksheets;
                    foreach (var worksheet in worksheets)
                    {
                        GenerateClass(worksheet, stringBuilder);
                    }
                    stringBuilder.AppendLine("}\r\n");
                }
                File.WriteAllText(CodeDir + $"/{fileName}.cs", stringBuilder.ToString());
                Console.WriteLine($"{fileName}.cs 脚本成功生成");
                //Console.WriteLine(stringBuilder);
            }
        }
        /// <summary>
        /// 生成数据结构
        /// </summary>
        private void GenerateClass(ExcelWorksheet worksheet, StringBuilder stringBuilder)
        {
            object[,] Cells = (object[,])worksheet.Cells.Value;
            string Space = "    ";
            if (Cells[0, 0].ToString() == "上下模式")
            {
                stringBuilder.AppendLine(Space + "/// <summary>");
                stringBuilder.AppendLine(Space + $"/// {Cells[0, 1]}");
                stringBuilder.AppendLine(Space + "/// <summary>");
                stringBuilder.AppendLine(Space + $"public class {worksheet.Name}");
                stringBuilder.AppendLine(Space + "{");
                int col = 0;
                while (Cells[1, col] != null && Cells[2, col] != null)
                {
                    if (Cells[3, col] != null)
                    {
                        stringBuilder.AppendLine(Space + Space + "/// <summary>");
                        stringBuilder.AppendLine(Space + Space + $"/// {Cells[3, col]}");
                        stringBuilder.AppendLine(Space + Space + "/// <summary>");
                    }
                    stringBuilder.AppendLine(Space + Space + $"public {Cells[2, col]} {Cells[1, col]}  {{ get; set; }}");
                    col++;
                }
                stringBuilder.AppendLine(Space + "}");
            }
            else                        // 左右模式
            {
                stringBuilder.AppendLine(Space + "/// <summary>");
                stringBuilder.AppendLine(Space + $"/// {Cells[1, 0]}");
                stringBuilder.AppendLine(Space + "/// <summary>");
                stringBuilder.AppendLine(Space + $"public class {worksheet.Name}");
                stringBuilder.AppendLine(Space + "{");
                int row = 0;
                while (Cells[row, 1] != null && Cells[row, 2] != null)
                {
                    if (Cells[row, 3] != null)
                    {
                        stringBuilder.AppendLine(Space + Space + "/// <summary>");
                        stringBuilder.AppendLine(Space + Space + $"/// {Cells[row, 3]}");
                        stringBuilder.AppendLine(Space + Space + "/// <summary>");
                    }
                    stringBuilder.AppendLine(Space + Space + $"public {Cells[row, 2]} {Cells[row, 1]}  {{ get; set; }}");
                    row++;
                }
                stringBuilder.AppendLine(Space + "}");
            }
        }

        /// <summary>
        /// 向JObject 添加一条字段
        /// </summary>
        private void AddJObjectField(JObject jObj, string key, string typeStr, string valueStr)
        {
            typeStr = typeStr.ToLower();
            if (typeStr == "bool")
            {
                bool.TryParse(valueStr, out bool value);
                jObj[key] = value;
            }
            else if (typeStr == "int")
            {
                int.TryParse(valueStr, out int value);
                jObj[key] = value;
            }
            else if (typeStr == "float")
            {
                float.TryParse(valueStr, out float value);
                jObj[key] = value;
            }
            else if (typeStr == "string")
            {
                jObj[key] = valueStr;
            }
            else if (typeStr == "bool[]")
            {
                string[] strings = valueStr.Split(',');
                bool[] bools = Array.ConvertAll(strings, new Converter<string, bool>((str) =>
                {
                    bool.TryParse(str, out bool b);
                    return b;
                }));
                JArray jArr = new JArray(bools);
                jObj[key] = jArr;
            }
            else if (typeStr == "int[]")
            {
                string[] strings = valueStr.Split(',');
                int[] ints = Array.ConvertAll(strings, new Converter<string, int>((str) =>
                {
                    int.TryParse(str, out int i);
                    return i;
                }));
                JArray jArr = new JArray(ints);
                jObj[key] = jArr;
            }
            else if (typeStr == "float[]")
            {
                string[] strings = valueStr.Split(',');
                float[] floats = Array.ConvertAll(strings, new Converter<string, float>((str) =>
                {
                    float.TryParse(str, out float f);
                    return f;
                }));
                JArray jArr = new JArray(floats);
                jObj[key] = jArr;
            }
            else if (typeStr == "string[]")
            {
                string[] strings = valueStr.Split(',');
                JArray jArr = new JArray(strings);
                jObj[key] = jArr;
            }
            else
            {
                int.TryParse(valueStr, out int index);
                key = $"{key}&{typeStr}&{index}";
                jObj[key] = null;
            }
        }
        public void Run()
        {
            // 初始化
            if (!Init()) return;
            // 使用Epplus 库遵守非商业使用许可证
            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
            Console.WriteLine("------生成代码------");
            // 生成C#
            GenerateCode();
            Console.WriteLine("------生成Json------");
            // 生成 Json
            GenerateJson();

            Console.WriteLine("--------结束--------");
        }
        /// <summary>
        /// 生成 Json配置
        /// </summary>
        private void GenerateJson()
        {
            Dictionary<string, JArray> Jsons = new Dictionary<string, JArray>();
            string[] excelFiles = Directory.GetFiles(ExcelDir, "*.xlsx");
            foreach (string excelFile in excelFiles)
            {
                using (var package = new ExcelPackage(excelFile))
                {
                    var worksheets = package.Workbook.Worksheets;
                    foreach (var worksheet in worksheets)
                    {
                        JArray array = new JArray();
                        GenerateJsonItem(worksheet, array);
                        Jsons.Add(worksheet.Name.ToLower(), array);
                        //Console.WriteLine(worksheet.Name + "生成Json成功");
                        //Console.WriteLine(array.ToString());
                    }
                }
            }
            GenerateJsonData(Jsons);
        }
        /// <summary>
        /// 对单个Json数据类型处理
        /// </summary>
        private void GenerateJsonItem(ExcelWorksheet worksheet, JArray jArr)
        {
            object[,] Cells = (object[,])worksheet.Cells.Value;
            List<string> fields = new List<string>();
            List<string> types = new List<string>();
            if (Cells[0, 0].ToString() == "上下模式")
            {
                // 字段和类型解析
                int col = 0;
                while (Cells[1, col] != null && Cells[2, col] != null)
                {
                    fields.Add((string)Cells[1, col]);
                    types.Add((string)Cells[2, col]);
                    col++;
                }
                // 数据解析
                int row = 4;
                while (Cells[row, 0] != null)
                {
                    JObject jObj = new JObject();
                    for (int x = 0; x < fields.Count; x++)
                    {
                        AddJObjectField(jObj, fields[x], types[x], Cells[row, x].ToString());
                    }
                    jArr.Add(jObj);
                    row++;
                }
            }
            else
            {
                // 字段和类型解析
                int row = 0;
                while (Cells[row, 1] != null && Cells[row, 2] != null)
                {
                    fields.Add((string)Cells[row, 1]);
                    types.Add((string)Cells[row, 2]);
                    row++;
                }
                // 数据解析
                int col = 4;
                while (Cells[0, col] != null)
                {
                    JObject jObj = new JObject();
                    for (int y = 0; y < fields.Count; y++)
                    {
                        AddJObjectField(jObj, fields[y], types[y], Cells[y, col].ToString());
                    }
                    jArr.Add(jObj);
                    col++;
                }
            }
        }
        /// <summary>
        /// 对Json 引用表对象数据进行处理并生产Json文件
        /// </summary>
        private void GenerateJsonData(Dictionary<string, JArray> Jsons)
        {
            foreach (var json in Jsons)
            {
                foreach (JObject jObj in json.Value)
                {
                    JProperty[] jpArray = jObj.Properties().ToArray();
                    for (int i = 0; i < jpArray.Length; i++)
                    {
                        JProperty jProperty = jpArray[i];
                        string[] strs = jProperty.Name.Split('&');
                        if (strs.Length == 3)
                        {
                            int index = int.Parse(strs[2]);
                            if (jObj.Remove(jProperty.Name))
                            {
                                jObj[strs[0]] = Jsons[strs[1]][index];
                            }
                        }
                    }
                }
                Console.WriteLine(json.Key + ".json 生成Json成功");
                if (json.Value.Count == 1)
                {
                    File.WriteAllText(JsonDir + $"/{json.Key}.json", json.Value[0].ToString());
                    //Console.WriteLine(json.Value[0]);
                }
                else
                {
                    File.WriteAllText(JsonDir + $"/{json.Key}.json", json.Value.ToString());
                    //Console.WriteLine(json.Value);
                }
            }
        }
    }
}